home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 49
/
Amiga Format CD49 (2000-01-17)(Future Publishing)(GB)(Track 1 of 3)[!][issue 2000-02].iso
/
-serious-
/
misc
/
db3.6-beta
/
db3.6-beta-src
/
design.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-11-30
|
52KB
|
1,512 lines
#include <exec/types.h>
#include <intuition/intuition.h>
#include <libraries/gadtools.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/gadtools.h>
#include <proto/utility.h>
#include <proto/exec.h> /* CopyMem() */
#include <string.h> /* strcpy */
#include <stdlib.h> /* abs() macro */
#include "Design.h"
#include "dbGUI.h"
#include "dbparser.h"
#include "Toolbox.h"
#include "DesignGUI.h"
#include "Version.h"
#include "Pointers.h"
#include <stdio.h> // Diagnostics
/*
* Externs to make the new GadToolsBox interface work
* Remove "static" from these in DesignGUI.c
*/
extern struct Gadget *VisGadgets[];
extern struct Window *VisWnd;
extern struct NewMenu DesignNewMenu[];
extern struct Menu *DesignMenus;
#define CURSORWIDTH 3
#define DRAGTRESHOLD 6
#define TOGGLE_LED *(UBYTE *)0xbfe001 ^= 2 /* Debug */
/* Handy macros */
#define FLOOR(x,f) if ((x)<(f)) (x) = (f)
/* Return codes from GadToolBox handlers */
#define RET_OK 1
#define RET_CANCEL 2
extern WORD LastLeftEdge;
extern WORD LastTopEdge; /* For nice layoutswitching */
extern void UpdateWindow(struct Pro *Pr);
extern void UpdateDragBar(struct Pro *Pr);
typedef int Bool; /* A char would be smaller, but will produce non-cast warnings */
typedef struct {
struct VisFldInfo *vf;
Bool after; /* Has cursor passed field? (to the left or right of field) */
} Cursor;
struct EasyStruct ES_ViewDesignHelp =
{
sizeof(struct EasyStruct),
0,
(STRPTR)"View design",
(STRPTR)"%s",
(STRPTR)"Ok"
};
/**********************************************************************/
/* Globals */
/**********************************************************************/
Cursor Crsr;
struct VisFldInfo *Selected; /* The selected field that has a rubberband */
int DragCnt = 0; /* Non-zero if dragging Selected. */
Bool Sizing = FALSE;
struct Window *ToolBox = NULL;
/* GadToolBox handlers uses global variables */
extern struct Pro *CurrentPro;
struct VisFldInfo *Vf;
extern char *RFFTagNames[];
/* The clipboard */
struct VisFldInfo *Clip = NULL;
/**********************************************************************/
/* Support functions */
/**********************************************************************/
struct VisFldInfo *PrevVisFldInfo(struct Layout *Lay, struct VisFldInfo *vf)
{
struct VisFldInfo *t = Lay->FirstVisFldInfo;
if (t == vf) return NULL;
for (; t; t = t->Next) if (t->Next == vf) return t;
return NULL; /* Safety */
}
static void InitCursor(struct Layout *Lay, Cursor *crsr)
{
crsr->vf = Lay->FirstVisFldInfo;
crsr->after = FALSE;
}
static void GetCursorPosition(Cursor *crsr, WORD *x, WORD *y)
{
/* Return position of cursor in (x,y) coords */
if (crsr->vf) {
*y = crsr->vf->Pos.YOffset;
*x = crsr->vf->Pos.XOffset;
*x += (crsr->after) ? crsr->vf->Pos.Width + CURSORWIDTH : -2*CURSORWIDTH;
}
else {
*x = OffX + FontX; /* As in CalcAllPos() */
*y = OffY + (FontY >> 1); /* As in CalcAllPos() */
}
}
static int PreviousPosition(struct Layout *Lay, Cursor *crsr)
{
/* Position cursor one step to the left (maybe up) */
/* Return FALSE if this is not possible */
struct VisFldInfo *vf;
if (!crsr->vf) return FALSE; /* No gadgets at all */
if (crsr->after) {
crsr->after = FALSE;
return TRUE;
}
else if (vf = PrevVisFldInfo(Lay, crsr->vf)) {
crsr->vf = vf;
crsr->after = TRUE;
return TRUE;
}
return FALSE;
}
static int NextPosition(struct Layout *Lay, Cursor *crsr)
{
/* Position cursor one step to the right (maybe down) */
/* Return FALSE if this is not possible */
if (!crsr->vf) return FALSE; /* No gadgets at all */
if (!crsr->after) {
crsr->after = TRUE;
return TRUE;
}
else if (crsr->vf->Next) {
crsr->vf = crsr->vf->Next;
crsr->after = FALSE;
return TRUE;
}
return FALSE;
}
static void DisplayCursor(struct RastPort *rp, WORD x, WORD y)
{
/* Draws a cursor in complement colour at given position */
/* Deletes cursor at old position automatically */
/* Specify a negative coordinate in either x or y to remove cursor */
/* DisplayCursor assumes a locked cursorheight */
static WORD oldx = -1, oldy = -1;
SetDrMd(rp, COMPLEMENT);
if (oldx>=0 && oldy>=0)
RectFill(rp, oldx, oldy, oldx+CURSORWIDTH-1, oldy+FontY+STRGADFRAMESHEIGHT-1);
if (x>=0 && y>=0)
RectFill(rp, x, y, x+CURSORWIDTH-1, y+FontY+STRGADFRAMESHEIGHT-1);
oldx = x;
oldy = y;
}
static void Rubberband(struct RastPort *rp, WORD left, WORD top, WORD width, WORD height, char handle)
{
/* Draws a border rectangle in complement colour. Adds a handle square if "handle" is TRUE */
/* Deletes old rubberband automatically */
/* Specify a negative coordinate in either left or top to remove rubberband */
static WORD oldleft = -1, oldtop = -1, oldwidth=-1, oldheight=-1, oldhandle = 0;
SetDrMd(rp, COMPLEMENT);
left--; top--; width++; height++;
if (oldleft>=0 && oldtop>=0) {
Move(rp, oldleft, oldtop);
Draw(rp, oldleft+oldwidth, oldtop);
Draw(rp, oldleft+oldwidth, oldtop+oldheight);
Draw(rp, oldleft, oldtop+oldheight);
Draw(rp, oldleft, oldtop);
if (oldhandle) { /* Draw a 3x4 square in the middle of the right border */
RectFill(rp, oldleft+oldwidth+1, oldtop+(oldheight>>1), oldleft+oldwidth+4, oldtop+(oldheight>>1)+2);
}
}
if (left>=0 && top>=0) {
Move(rp, left, top);
Draw(rp, left+width, top);
Draw(rp, left+width, top+height);
Draw(rp, left, top+height);
Draw(rp, left, top);
if (handle) { /* Draw a 3x4 square in the middle of the right border */
RectFill(rp, left+width+1, top+(height>>1), left+width+4, top+(height>>1)+2);
}
}
oldleft = left; oldtop = top; oldwidth = width; oldheight = height; oldhandle = handle;
}
void FollowMouse(struct Layout *Lay, WORD mx, WORD my)
{
/* Moves the cursor to the position that is nearest to (x,y) */
Cursor nearest;
WORD x,y;
WORD nx, ny;
if (!Crsr.vf) return;
while (PreviousPosition(Lay, &Crsr)); /* Go to the beginning */
nearest = Crsr;
GetCursorPosition(&nearest, &nx, &ny);
while (NextPosition(Lay, &Crsr)) {
GetCursorPosition(&Crsr, &x, &y);
if (abs(my-y) < abs(my-ny)) {
nearest = Crsr;
GetCursorPosition(&nearest, &nx, &ny);
}
if (abs(my-y) == abs(my-ny))
if (abs(mx-x) < abs(mx-nx)) {
nearest = Crsr;
GetCursorPosition(&nearest, &nx, &ny);
}
}
Crsr = nearest;
DisplayCursor(Lay->Window->RPort, nx, ny);
}
static struct VisFldInfo *VisFldHit(struct Layout *Lay, WORD x, WORD y)
{
/* Returns the address of the VisFldInfo that is hit by (x,y) */
struct VisFldInfo *vf = NULL;
for (vf = Lay->FirstVisFldInfo; vf; vf = vf->Next) {
if (x >= vf->Pos.XOffset && x < vf->Pos.XOffset+vf->Pos.Width &&
y >= vf->Pos.YOffset && y < vf->Pos.YOffset+vf->Pos.Height)
break;
}
return vf;
}
static Bool SizeHit(struct VisFldInfo *hit, WORD mouseX)
{
/* Return true if mouse is close to the right border of the "hit" field */
return (hit && (hit->Pos.XOffset + hit->Pos.Width - mouseX) < 5);
}
void SelectVisFld(struct Layout *Lay, struct VisFldInfo *vf)
{
if (Selected = vf) {
struct Space *sp = &Selected->Pos;
Rubberband(Lay->Window->RPort, sp->XOffset, sp->YOffset, sp->Width, sp->Height, 0);
}
else {
Rubberband(Lay->Window->RPort, -1, -1, -1, -1, 0);
}
}
static struct VisFldInfo *RemoveVisFldInfo(struct Layout *Lay, struct VisFldInfo *oldvf)
{
/* Remove oldvf from the layout and handle all side effects this may have */
struct VisFldInfo *prev;
if (!oldvf) return NULL;
prev = PrevVisFldInfo(Lay, oldvf);
if (prev) {
prev->Next = oldvf->Next;
if (oldvf->VisSep == '\n' || oldvf->VisSep == '\f') { /* end of line */
prev->VisSep = oldvf->VisSep;
WriteVisTags(prev); /* Update RFF tags in vf */
}
}
else Lay->FirstVisFldInfo = oldvf->Next;
/* Handle cursor and rubberband */
if (Crsr.vf == oldvf) {
if (Crsr.vf->Next) Crsr.vf = Crsr.vf->Next;
else Crsr.vf = prev; /* This might be NULL, and that's ok */
}
SelectVisFld(Lay, NULL);
return oldvf;
}
static void InsertVisFldInfo(struct Layout *Lay, struct VisFldInfo *vf)
{
/* Insert vf in the layout and handle all side effects this may have */
/* vf is placed at the cursor position */
struct VisFldInfo **link_here;
if (!Lay->FirstVisFldInfo) link_here = &Lay->FirstVisFldInfo;
else if (Crsr.after) {
link_here = &Crsr.vf->Next;
vf->VisSep = Crsr.vf->VisSep;
Crsr.vf->VisSep = ' ';
WriteVisTags(vf);
WriteVisTags(Crsr.vf);
}
else {
struct VisFldInfo *prevvf = PrevVisFldInfo(Lay, Crsr.vf);
if (!prevvf) link_here = &Lay->FirstVisFldInfo;
else link_here = &prevvf->Next;
vf->VisSep = ' ';
}
/* Link */
vf->Next = *link_here;
*link_here = vf;
// SelectVisFld(Lay, vf); /* Now, it's easy to spot the new field */
}
int DeleteUndo(struct Layout *Lay)
{
struct VisFldInfo *vf,*nextvf;
for (vf = Lay->FirstUndoVisFldInfo; vf; vf=nextvf) {
nextvf = vf->Next;
DeleteVisFldInfo(vf);
}
Lay->FirstUndoVisFldInfo = NULL;
OffMenu(CurrentPro->CurrentLayout->Window, FULLMENUNUM(1,0,NOSUB)); /* Edit->Undo */
return 0;
}
Bool PerformUndo(struct Layout *Lay)
{
struct VisFldInfo *tmp;
if (!Lay->FirstUndoVisFldInfo) return FALSE;
tmp = Lay->FirstVisFldInfo;
Lay->FirstVisFldInfo = Lay->FirstUndoVisFldInfo;
Lay->FirstUndoVisFldInfo = tmp;
Crsr.vf = Lay->FirstVisFldInfo;
Selected = NULL;
return TRUE;
}
Bool SaveUndo(struct Layout *Lay)
{
struct VisFldInfo *vf, **link_here;
DeleteUndo(Lay); /* Remove old undo */
link_here = &Lay->FirstUndoVisFldInfo;
for (vf = Lay->FirstVisFldInfo; vf; vf=vf->Next, link_here = &((*link_here)->Next)) {
if (!(*link_here = CopyVisFldInfo(vf))) return DeleteUndo(Lay);
}
OnMenu(CurrentPro->CurrentLayout->Window, FULLMENUNUM(1,0,NOSUB)); /* Edit->Undo */
CurrentPro->Modified |= PROMODIFIED;
return TRUE;
}
static int Redraw(struct Pro *Pr, struct Layout *Lay)
{
/* Recalculates all gadgets and redraws the updated window */
WORD ww, wh;
WORD x,y;
int ret;
Bool ok = TRUE;
/* Tear down */
DisplayCursor(Lay->Window->RPort, -1, -1);
Rubberband(Lay->Window->RPort, -1, -1, -1, -1, 0);
/* Rebuild with undo fallback */
do {
if ((ret = CalcAllPos(Pr, Lay, &ww, &wh)) >= 0) {
if ((ret = CreateAllGadgets(Pr, Lay, ww, wh, DESIGN_MODE)) >= 0) {
if ((ret = AttachAllGadgets(Lay, ww, wh, DESIGN_MODE)) >= 0) {
DeleteAllGadgets(Lay, DESIGN_MODE);
GetCursorPosition(&Crsr, &x, &y);
DisplayCursor(Lay->Window->RPort, x, y);
SelectVisFld(Lay, Selected); /* Update rubberband */
/* Update pointer */
if (SizeHit(VisFldHit(Lay, DB_Msg.MouseX, DB_Msg.MouseY), DB_Msg.MouseX))
ChangePointer(Lay->Window, LRPointer);
else RestorePointer(Lay->Window);
return ret;
}
}
DeleteAllGadgets(Lay, DESIGN_MODE);
}
DisplayBeep(Scr);
ok = PerformUndo(Lay);
DeleteUndo(Lay);
} while (ok);
return ret; /* This is serious trouble */
}
int DoEdit(struct Pro *Pr, struct VisFldInfo *vf)
{
/* Let the user perform the actual editing of a vf */
/* returns 0 if no changes has been made to vf */
struct FldInfo *f;
BOOL quit = FALSE;
ULONG field_type = _STRING, new_field_type = _STRING;
if (OpenVisWindow()) return 0;
/* Prepare gadgets */
GT_SetGadgetAttrs(VisGadgets[GD_VIS_NAME], VisWnd, NULL,
GTST_String, vf->Name, TAG_END);
GT_SetGadgetAttrs(VisGadgets[GD_VIS_SIZE], VisWnd, NULL,
GTIN_Number, vf->VisLen, TAG_END);
{
struct RFFTag *tag = FindTag(&vf->VisTags, FTYP);
if(tag)
{
if(!stricmp(tag->Data, STR_TEXT)) field_type = _TEXT;
if(!stricmp(tag->Data, STR_CYCLE)) field_type = _CYCLE;
if(!stricmp(tag->Data, STR_CHECKBOX)) field_type = _CHECKBOX;
if(!stricmp(tag->Data, STR_TEXTFIELD)) field_type = _TEXTFIELD;
}
}
GT_SetGadgetAttrs(VisGadgets[GD_VIS_TYPE], VisWnd, NULL,
GTCY_Active, field_type, TAG_END);
if (f = GetFldInfo(Pr, vf->Offset))
GT_SetGadgetAttrs(VisGadgets[GD_VIS_FIELD], VisWnd, NULL,
GTTX_Text, f->Name,
TAG_END);
else GT_SetGadgetAttrs(VisGadgets[GD_VIS_FIELD], VisWnd, NULL,
GTTX_Text, GetAppStr(MSG_EDVIEW_SELECT),
TAG_END);
Vf = vf; /* GadTooBox handlers use global variables */
/* Handle input */
while (!quit)
{
WaitPort(VisWnd->UserPort);
quit = HandleVisIDCMP();
}
GT_GetGadgetAttrs(VisGadgets[GD_VIS_TYPE], VisWnd, NULL,
GTCY_Active, &new_field_type, TAG_END);
CloseVisWindow(); /* GadToolBox automatically NULLs pointers */
if (quit == RET_CANCEL) return 0;
/* update vf */
strcpy(vf->Name, GetStringGadget(VisGadgets[GD_VIS_NAME]));
vf->VisLen = GetNumber(VisGadgets[GD_VIS_SIZE]);
if(new_field_type != field_type)
{
struct RFFTag *tag;
while(tag = FindTag(&vf->VisTags, CENT))
{
Remove((struct Node *)tag);
DeleteTag(tag);
}
switch(new_field_type)
{
case _STRING:
{
struct RFFTag *tag;
tag = FindTag(&vf->VisTags, FTYP);
if(tag)
{
Remove((struct Node *)tag);
DeleteTag(tag);
}
}
break;
case _TEXT:
UpdateTag(&vf->VisTags, FTYP, STR_TEXT);
break;
case _CHECKBOX:
UpdateTag(&vf->VisTags, FTYP, STR_CHECKBOX);
break;
case _TEXTFIELD:
UpdateTag(&vf->VisTags, FTYP, STR_TEXTFIELD);
break;
case _CYCLE:
UpdateTag(&vf->VisTags, FTYP, STR_CYCLE);
CreateAndAddTag(&vf->VisTags, CENT, GetAppStr(MSG_EDVIEW_CYCLE_1));
CreateAndAddTag(&vf->VisTags, CENT, GetAppStr(MSG_EDVIEW_CYCLE_2));
CreateAndAddTag(&vf->VisTags, CENT, GetAppStr(MSG_EDVIEW_CYCLE_3));
break;
}
}
WriteVisTags(vf); /* Update RFF tags in vf */
/* As user might have connected the vf to an internal field of cycle type,
* we must then remake the cycle list by reading the VisTags
*/
if (ReadVisTags(Pr, vf) < 0) return 0;
/* vf->Offset and the tags has been updated inside GadToolBox */
return 1; /* Use */
}
void ReplaceVisFldInfo(struct Layout *Lay, struct VisFldInfo *old, struct VisFldInfo *new)
{
struct VisFldInfo *prev = PrevVisFldInfo(Lay, old);
new->Next = old->Next;
if (prev) prev->Next = new;
else Lay->FirstVisFldInfo = new;
/* Don't forget to make sure that the cursor and rubberband points correctly */
if (Crsr.vf == old) Crsr.vf = new;
if (Selected == old) Selected = new;
}
static void EditVisFldInfo(struct Pro *Pr, struct Layout *Lay, struct VisFldInfo *vf)
{
struct VisFldInfo *copy = CopyVisFldInfo(vf);
if (!copy) return;
for (;;) {
if (!DoEdit(Pr, copy)) { /* Cancel */
DeleteVisFldInfo(copy);
Redraw(Pr, Lay);
return;
}
else {
ReplaceVisFldInfo(Lay, vf, copy);
if (Redraw(Pr, Lay) < 0) { /* Oops, this didn't fit on screen */
ReplaceVisFldInfo(Lay, copy, vf);
}
else break;
}
}
DeleteVisFldInfo(vf);
}
/**********************************************************************/
/* Event handlers */
/**********************************************************************/
static void CloseDesignWin(struct Layout *Lay)
{
if (Lay->Window) {
DisplayCursor(Lay->Window->RPort, -1, -1); /* Remove cursor */
Rubberband(Lay->Window->RPort, -1, -1, -1, -1, 0); /* Remove rubberband */
/* Remember old window pos */
LastLeftEdge = Lay->Window->LeftEdge;
LastTopEdge = Lay->Window->TopEdge;
ClearMenuStrip(Lay->Window);
FreeMenus( DesignMenus );
DesignMenus = NULL;
CloseWindow(Lay->Window);
Lay->Window = NULL;
}
}
static int RawKey(struct Pro *Pr, struct Layout *Lay)
{
WORD x,y;
WORD oldx,oldy;
struct VisFldInfo *oldpos = Crsr.vf;
switch (DB_Msg.Code) {
/* case RAW_F10:
Redraw(Pr, Lay);
return 0;
break; // Looks nice :-)
case RAW_F10-3:
DeleteUndo(Lay);
printf("DeleteUndo\n");
break;
case RAW_F10-2:
SaveUndo(Lay);
printf("Save\n");
break;
case RAW_F10-1:
PerformUndo(Lay);
Redraw(Pr, Lay);
break;
*/
case RAW_F1:
ToolBoxClicked(Pr, Lay, StringID);
break;
case RAW_F2:
ToolBoxClicked(Pr, Lay, TextID);
break;
case RAW_F3:
ToolBoxClicked(Pr, Lay, TextFieldID);
break;
case RAW_F4:
ToolBoxClicked(Pr, Lay, CycleID);
break;
case RAW_F5:
ToolBoxClicked(Pr, Lay, CheckBoxID);
break;
case RAW_HELP:
EasyRequest(Lay->Window, &ES_ViewDesignHelp, NULL, GetAppStr(MSG_EDVIEW_HELP_BODY));
break;
case RAW_LEFT:
PreviousPosition(Lay, &Crsr);
break;
case RAW_RIGHT:
NextPosition(Lay, &Crsr);
break;
case RAW_UP:
GetCursorPosition(&Crsr, &oldx, &oldy);
while (PreviousPosition(Lay, &Crsr)) {
GetCursorPosition(&Crsr, &x, &y);
if (y < oldy && x <= oldx) break;
}
break;
case RAW_DOWN:
GetCursorPosition(&Crsr, &oldx, &oldy);
while (NextPosition(Lay, &Crsr)) {
GetCursorPosition(&Crsr, &x, &y);
if (y > oldy) {
oldy = y;
break;
}
}
while (NextPosition(Lay, &Crsr)) {
GetCursorPosition(&Crsr, &x, &y);
if (y > oldy || x > oldx) {
PreviousPosition(Lay, &Crsr);
break;
}
}
break;
}
GetCursorPosition(&Crsr, &x, &y);
DisplayCursor(Lay->Window->RPort, x, y);
if (Crsr.vf != oldpos) SelectVisFld(Lay, NULL); /* Cursor has moved, so clear rubberband */
return 0;
}
static int VanillaKey(struct Pro *Pr, struct Layout *Lay)
{
struct VisFldInfo *vf = NULL;
char oldVisSep;
SaveUndo(Lay);
switch (DB_Msg.Code) {
case '\r':
if (Crsr.after) vf = Crsr.vf;
else vf = PrevVisFldInfo(Lay, Crsr.vf);
if (!vf) break;
oldVisSep = vf->VisSep;
switch (vf->VisSep) {
case ' ':
case '\t':
vf->VisSep = '\n';
break;
case '\n':
vf->VisSep = '\f';
break;
}
break;
case '\t':
if (Crsr.after) vf = Crsr.vf;
else vf = PrevVisFldInfo(Lay, Crsr.vf);
if (!vf) break;
oldVisSep = vf->VisSep;
if (vf->VisSep == ' ') {
vf->VisSep = '\t';
}
break;
case '\b':
if (Crsr.after) break;
else vf = PrevVisFldInfo(Lay, Crsr.vf);
if (!vf) break;
oldVisSep = vf->VisSep;
switch (vf->VisSep) {
case '\t':
case '\n':
vf->VisSep = ' ';
break;
case '\f':
vf->VisSep = '\n';
break;
}
break;
case VANILLA_DEL:
if (Selected) { /* Delete the selected field */
SaveUndo(Lay);
DeleteVisFldInfo(RemoveVisFldInfo(Lay, Selected));
Redraw(Pr, Lay);
return 0;
}
else {
if (!Crsr.after) break;
else vf = Crsr.vf;
if (!vf) break;
oldVisSep = vf->VisSep;
switch (vf->VisSep) {
case '\t':
case '\n':
vf->VisSep = ' ';
break;
case '\f':
vf->VisSep = '\n';
break;
}
}
break;
case VANILLA_ESC:
return 1; /* Exit design mode */
break;
}
if (vf && vf->VisSep != oldVisSep) {
if (Redraw(Pr, Lay) < 0) { /* Oops, this didn't fit on screen */
DisplayBeep(Scr);
vf->VisSep = oldVisSep;
if (Redraw(Pr, Lay) < 0) ByeBye(); /* This should never happen */
}
WriteVisTags(vf); /* Update RFF tags in vf */
}
return 0;
}
int MouseButtons(struct Pro *Pr, struct Layout *Lay)
{
static ULONG StartSeconds=0, StartMicros=0;
struct VisFldInfo *oldselected = Selected;
if (Selected = VisFldHit(Lay, DB_Msg.MouseX, DB_Msg.MouseY)) {
struct Space *sp = &Selected->Pos;
Rubberband(Lay->Window->RPort, sp->XOffset, sp->YOffset, sp->Width, sp->Height, 0);
if (DoubleClick(StartSeconds, StartMicros, DB_Msg.Seconds, DB_Msg.Micros) &&
Selected == oldselected) {
if (DragCnt) { /* Cancel dragging */
DragCnt = 0;
RestorePointer(Lay->Window);
}
EditVisFldInfo(Pr, Lay, Selected);
StartSeconds = StartMicros = 0; /* Prevent "triple clicks" */
}
else {
StartSeconds = DB_Msg.Seconds; StartMicros = DB_Msg.Micros;
if (Selected) {
if (SizeHit(Selected, DB_Msg.MouseX)) {
Sizing = TRUE;
Forbid();
Lay->Window->Flags |= WFLG_RMBTRAP;
Permit();
}
else DragCnt = 1; /* Initiate dragging */
}
}
}
else {
Rubberband(Lay->Window->RPort, -1, -1, -1, -1, 0);
FollowMouse(Lay, DB_Msg.MouseX, DB_Msg.MouseY);
}
return 0;
}
static void ToolBoxClicked(struct Pro *Pr, struct Layout *Lay, int gadgetID)
{
struct VisFldInfo *vf;
/* Make a VisFldInfo */
if (!(vf = NewVisFldInfo())) return;
/* Fill in type (string, cycle, checkbox, textfield or text) */
switch (gadgetID) {
case CheckBoxID:
CreateAndAddTag(&vf->VisTags, FTYP, STR_CHECKBOX);
vf->VisLen = 3; /* smaller is better */
break;
case TextID:
CreateAndAddTag(&vf->VisTags, FTYP, STR_TEXT);
vf->VisLen = 10;
break;
case TextFieldID:
if(TextFieldClass)
{
CreateAndAddTag(&vf->VisTags, FTYP, STR_TEXTFIELD);
CreateAndAddTag(&vf->VisTags, ROWS, "4");
vf->VisLen = 15;
}
break;
case CycleID:
CreateAndAddTag(&vf->VisTags, FTYP, STR_CYCLE);
CreateAndAddTag(&vf->VisTags, CENT, GetAppStr(MSG_EDVIEW_CYCLE_1));
CreateAndAddTag(&vf->VisTags, CENT, GetAppStr(MSG_EDVIEW_CYCLE_2));
CreateAndAddTag(&vf->VisTags, CENT, GetAppStr(MSG_EDVIEW_CYCLE_3));
vf->VisLen = 16; /* smaller is better */
break;
}
ReadVisTags(Pr, vf); /* This way we get the cycle-list in vf */
vf->Name[0] = '\0';
/* Release the user */
if (!DoEdit(Pr, vf)) { /* Cancel */
DeleteVisFldInfo(vf);
return;
}
InsertVisFldInfo(Lay, vf); /* link it */
if (Redraw(Pr, Lay) < 0) { /* Oops, this didn't fit on screen */
DisplayBeep(Scr);
DeleteVisFldInfo(RemoveVisFldInfo(Lay, vf));
Redraw(Pr, Lay);
}
if (!Crsr.vf) Crsr.vf = Lay->FirstVisFldInfo; /* Move cursor on-track */
}
/**********************************************************************/
/* IDCMP handler */
/**********************************************************************/
static int DesignWindowIDCMP(struct Pro *Pr, struct Layout *Lay)
{
struct IntuiMessage *m;
struct MenuItem *n;
int (*func)(void);
struct Window *Win = Lay->Window;
ULONG signals, winsig, toolboxsig = 0;
BOOL running = TRUE;
winsig = 1L << Win->UserPort->mp_SigBit;
if (ToolBox) toolboxsig = 1L << ToolBox->UserPort->mp_SigBit;
for (;;) {
// WaitPort(Win->UserPort);
signals = Wait(winsig | toolboxsig);
if (signals & winsig) {
while( m = GT_GetIMsg( Win->UserPort )) {
CopyMem(( char * )m, ( char * )&DB_Msg, (long)sizeof( struct IntuiMessage ));
GT_ReplyIMsg( m );
switch ( DB_Msg.Class ) {
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh(Win);
GT_EndRefresh(Win, TRUE );
break;
case IDCMP_CLOSEWINDOW:
return 0;
break;
case IDCMP_NEWSIZE:
// // printf("IDCMP_NEWSIZE\n");
if (!(Win->Flags & WFLG_ZOOMED)) Redraw(Pr, Lay);
break;
case IDCMP_VANILLAKEY:
// // printf("IDCMP_VANILLAKEY\n");
running = VanillaKey(Pr, Lay);
if (running) return running;
break;
case IDCMP_RAWKEY:
// // printf("IDCMP_RAWKEY\n");
running = RawKey(Pr, Lay);
break;
case IDCMP_MOUSEMOVE:
{
if (Sizing) {
Selected->Pos.Width = DB_Msg.MouseX - Selected->Pos.XOffset;
FLOOR(Selected->Pos.Width, FontX+STRGADFRAMESWIDTH);
SelectVisFld(Lay, Selected); /* Update rubberband */
break;
}
else if (DragCnt) {
if (DragCnt++ == DRAGTRESHOLD) {
ChangePointer(Win, MovePointer);
Forbid();
Win->Flags |= WFLG_RMBTRAP;
Permit();
}
FollowMouse(Lay, DB_Msg.MouseX, DB_Msg.MouseY);
}
else if (SizeHit(VisFldHit(Lay, DB_Msg.MouseX, DB_Msg.MouseY), DB_Msg.MouseX))
ChangePointer(Win, LRPointer);
else RestorePointer(Win);
}
// printf("IDCMP_MOUSEMOVE\n");
break;
case IDCMP_MOUSEBUTTONS:
if (DB_Msg.Code == SELECTDOWN) {
running = MouseButtons(Pr, Lay);
}
else if (DB_Msg.Code == SELECTUP) {
if (Win->Flags & WFLG_RMBTRAP) { /* Enable menu button again */
Forbid();
Win->Flags &= ~WFLG_RMBTRAP;
Permit();
}
if (DragCnt >= DRAGTRESHOLD) {
RestorePointer(Win);
if (Crsr.vf != Selected) { /* Move it */
SaveUndo(Lay);
InsertVisFldInfo(Lay, RemoveVisFldInfo(Lay, Selected));
Redraw(Pr, Lay);
}
}
else if (Sizing) {
Sizing = FALSE;
SaveUndo(Lay);
Selected->VisLen = (Selected->Pos.Width+(FontX+1)/2-STRGADFRAMESWIDTH)/FontX;
WriteVisTags(Selected); /* Update RFF tags in vf */
Redraw(Pr, Lay);
}
DragCnt = 0;
}
else if (DB_Msg.Code == MENUUP) { /* Cancel */
if (Win->Flags & WFLG_RMBTRAP) { /* Enable menu button again */
Forbid();
Win->Flags &= ~WFLG_RMBTRAP;
Permit();
}
if (DragCnt) { /* Cancel dragging */
DragCnt = 0;
RestorePointer(Win);
}
else if (Sizing) { /* Cancel sizechange */
Sizing = FALSE;
Redraw(Pr, Lay);
}
}
break;
case IDCMP_MENUPICK:
while( DB_Msg.Code != MENUNULL ) {
n = ItemAddress( Win->MenuStrip, DB_Msg.Code );
func = (int (*)(void))(GTMENUITEM_USERDATA( n ));
running = func();
if (running) return running; /* The window has been closed! */
DB_Msg.Code = n->NextSelect;
}
break;
}
}
} /* winsig signals */
if (signals & toolboxsig) {
while( m = GT_GetIMsg( ToolBox->UserPort )) {
CopyMem(( char * )m, ( char * )&DB_Msg, (long)sizeof( struct IntuiMessage ));
GT_ReplyIMsg( m );
switch ( DB_Msg.Class ) {
case IDCMP_GADGETUP:
// printf("Gadget up\n");
ActivateWindow(Win);
ToolBoxClicked(Pr, Lay, ((struct Gadget *)DB_Msg.IAddress)->GadgetID);
break;
}
}
} /* toolbox signals */
}
return( running );
}
char TitleBuffer[80];
static int DoOpenDesignWindow(struct Pro *Pr, struct Layout *Lay, WORD ww, WORD wh)
{
/* Does the actual opening (in DESIGN_MODE) */
WORD leftedge, topedge;
/* Position window nicely */
if (LastLeftEdge == -1) { /* No previous window to use */
leftedge = (Scr->Width - ww) >> 1; /* Middle */
topedge = (Scr->Height-wh) >> 1; /* Middle */
}
else {
leftedge = LastLeftEdge;
topedge = LastTopEdge;
}
/* We create this menu every time we enter view design */
if ( ! ( DesignMenus = CreateMenus( DesignNewMenu, TAG_DONE )))
return( 3L );
LayoutMenus( DesignMenus, VisualInfo, GTMN_NewLookMenus, TRUE, TAG_DONE );
/* Localization. Not optimal, but works ;-) */
ES_ViewDesignHelp.es_Title = GetAppStr(MSG_EDVIEW_HELP_TITLE);
ES_ViewDesignHelp.es_GadgetFormat = GetAppStr(MSG_REQ_OK);
sprintf(TitleBuffer, GetAppStr(MSG_EDVIEW_SCR_TITLE), VERSION_NUMBER);
if ( ! ( Lay->Window = OpenWindowTags( NULL,
WA_Left, leftedge,
WA_Top, topedge,
WA_Width, ww,
WA_Height, wh,
WA_IDCMP, IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE|IDCMP_NEWSIZE|IDCMP_MENUPICK|IDCMP_CLOSEWINDOW|IDCMP_RAWKEY|IDCMP_VANILLAKEY|IDCMP_REFRESHWINDOW,
WA_Flags, WFLG_REPORTMOUSE|WFLG_NEWLOOKMENUS|WFLG_DRAGBAR|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_SMART_REFRESH|WFLG_ACTIVATE,
WA_Gadgets, Lay->GList,
WA_Title, GetAppStr(MSG_EDVIEW_WIN_TITLE),
WA_ScreenTitle, TitleBuffer,
WA_PubScreen, Scr,
WA_Zoom, DB_Zoom,
// WA_MenuHelp, TRUE,
TAG_DONE )))
return WIN_ERR;
SetMenuStrip( Lay->Window, DesignMenus );
GT_RefreshWindow( Lay->Window, NULL);
/* Now detach all gadgets from the window as this is the design mode */
RemoveGList(Lay->Window, Lay->GList, -1);
/* We delete the gadgets and just leave the imagery */
DeleteAllGadgets(Lay, DESIGN_MODE);
/* For IDCMP handling used in this file */
WinSig = 1L << Lay->Window->UserPort->mp_SigBit;
return 0;
}
void FillClip(struct VisFldInfo *vf)
{
if (Clip) {
DeleteVisFldInfo(Clip);
}
Clip = vf;
}
/**********************************************************************/
/* Interface functions */
/**********************************************************************/
void Design(struct Pro *Pr, struct Layout *Lay)
{
/* This is the main function in the design system */
WORD ww, wh;
WORD x,y;
/* ww = Lay->Window->Width;
wh = Lay->Window->Height;
*/
CloseLayWin(Pr, Lay);
CalcAllPos(Pr, Lay, &ww, &wh); // Shouldn't be nessesary as we reopen the window
CreateAllGadgets(Pr, Lay, ww, wh, DESIGN_MODE);
DoOpenDesignWindow(Pr, Lay, ww, wh);
InitCursor(Lay, &Crsr);
Selected = NULL;
GetCursorPosition(&Crsr, &x, &y);
DisplayCursor(Lay->Window->RPort, x, y);
ToolBox = OpenToolBox(Lay->Window); /* "Parent" window */
DesignWindowIDCMP(Pr, Lay);
DeleteUndo(Lay);
FillClip(NULL);
CloseDesignWin(Lay);
if (ToolBox) {
CloseToolBox(ToolBox);
ToolBox = NULL;
}
OpenLayWin(Pr, Lay);
UpdateWindow(Pr);
UpdateDragBar(Pr);
/* Back to db run-mode */
}
/**********************************************************************/
/* GadToolBox handlers */
/**********************************************************************/
int LISTClicked( void )
{
/* routine when gadget "Object list" is clicked. */
return 0;
}
int TOPClicked( void )
{
/* routine when gadget "Top" is clicked. */
return 0;
}
int UPClicked( void )
{
/* routine when gadget "Up" is clicked. */
return 0;
}
int DOWNClicked( void )
{
/* routine when gadget "Down" is clicked. */
return 0;
}
int BOTTOMClicked( void )
{
/* routine when gadget "Bottom" is clicked. */
return 0;
}
int NEWClicked( void )
{
/* routine when gadget "_New..." is clicked. */
return 0;
}
int EDITClicked( void )
{
/* routine when gadget "_Edit..." is clicked. */
return 0;
}
int COPYClicked( void )
{
/* routine when gadget "Co_py" is clicked. */
return 0;
}
int REMOVEClicked( void )
{
/* routine when gadget "Remove" is clicked. */
return 0;
}
int USEClicked( void )
{
/* routine when gadget "_Use" is clicked. */
return 0;
}
int CANCELClicked( void )
{
/* routine when gadget "_Cancel" is clicked. */
return 0;
}
int TAG_VALUEClicked( void )
{
/* routine when gadget "_Value" is clicked. */
return 0;
}
int TAG_IDClicked( void )
{
/* routine when gadget "_ID" is clicked. */
return 0;
}
int TAG_OKClicked( void )
{
/* routine when gadget "_Ok" is clicked. */
return 0;
}
int TAG_CANCELClicked( void )
{
/* routine when gadget "_Cancel" is clicked. */
return 0;
}
int NAME_NAMEClicked( void )
{
/* routine when gadget "_Name" is clicked. */
return 0;
}
int NAME_OKClicked( void )
{
/* routine when gadget "_Ok" is clicked. */
return 0;
}
int NAME_CANCELClicked( void )
{
/* routine when gadget "_Cancel" is clicked. */
return 0;
}
int FIELD_NAMEClicked( void )
{
/* routine when gadget "_Name" is clicked. */
return 0;
}
int FIELD_MAXLENClicked( void )
{
/* routine when gadget "Max _length" is clicked. */
return 0;
}
int FIELD_OKClicked( void )
{
/* routine when gadget "_Ok" is clicked. */
return 0;
}
int FIELD_CANCELClicked( void )
{
/* routine when gadget "_Cancel" is clicked. */
return 0;
}
int FIELD_MOREClicked( void )
{
/* routine when gadget "_More..." is clicked. */
return 0;
}
int VIS_NAMEClicked( void )
{
/* routine when gadget "_Name" is clicked. */
return 0;
}
int VIS_SIZEClicked( void )
{
/* routine when gadget "Si_ze" is clicked. */
return 0;
}
int VIS_OKClicked( void )
{
/* routine when gadget "_Ok" is clicked. */
return RET_OK;
}
int VIS_CANCELClicked( void )
{
/* routine when gadget "_Cancel" is clicked. */
return RET_CANCEL;
}
int VIS_MOREClicked( void )
{
/* routine when gadget "_More..." is clicked. */
return 0;
}
int VIS_SELECTClicked( void )
{
/* routine when gadget "..." is clicked. */
Select *s;
struct FldInfo *f;
BOOL again = TRUE;
if (!(s = NewSelect())) {
DisplayBeep(Scr);
return 0;
}
for (f = CurrentPro->FirstFldInfo; f; f = f->Next)
AddStringLast(s, f->Name);
s->SelIndex = Vf->Offset;
OpenSelect(s, VisWnd, GetAppStr(MSG_EDVIEW_WIN_SELECT_TITLE), NULL);
while (again) {
WaitPort(s->SelWnd->UserPort);
switch(HandleSelectIDCMP(s)) {
case SEL_SELECT :
break;
case SEL_OK :
Vf->Offset = s->SelIndex;
GT_SetGadgetAttrs(VisGadgets[GD_VIS_FIELD], VisWnd, NULL,
GTTX_Text, SelectedString(s),
TAG_END);
again = FALSE;
break;
case SEL_CANCEL :
again = FALSE;
break;
case SEL_HELP :
break;
}
}
/*
CloseSelect(s);
RemoveAllStrings(s);
*/
DeleteSelect(s);
return 0;
}
int MainCloseWindow( void )
{
/* routine for "IDCMP_CLOSEWINDOW". */
return 1; /* i.e. Leave this mode */
}
int MainVanillaKey( void )
{
/* routine for "IDCMP_VANILLAKEY". */
return 0;
}
int MainRawKey( void )
{
/* routine for "IDCMP_RAWKEY". */
return 0;
}
int TagCloseWindow( void )
{
/* routine for "IDCMP_CLOSEWINDOW". */
return 0;
}
int TagVanillaKey( void )
{
/* routine for "IDCMP_VANILLAKEY". */
return 0;
}
int NameCloseWindow( void )
{
/* routine for "IDCMP_CLOSEWINDOW". */
return 0;
}
int NameVanillaKey( void )
{
/* routine for "IDCMP_VANILLAKEY". */
return 0;
}
int FieldCloseWindow( void )
{
/* routine for "IDCMP_CLOSEWINDOW". */
return 0;
}
int FieldVanillaKey( void )
{
/* routine for "IDCMP_VANILLAKEY". */
return 0;
}
int VisCloseWindow( void )
{
/* routine for "IDCMP_CLOSEWINDOW". */
return RET_CANCEL;
}
int VisVanillaKey( void )
{
/* routine for "IDCMP_VANILLAKEY". */
switch (ToUpper(VisMsg.Code)) {
case 'N':
ActivateGadget(VisGadgets[GD_VIS_NAME], VisWnd, NULL);
break;
case 'Z':
ActivateGadget(VisGadgets[GD_VIS_SIZE], VisWnd, NULL);
break;
case 'T':
{
ULONG active;
if(GT_GetGadgetAttrs(VisGadgets[GD_VIS_TYPE], VisWnd, NULL,
GTCY_Active, &active, TAG_END) == 1)
{
active = (active + 1) % 5;
GT_SetGadgetAttrs(VisGadgets[GD_VIS_TYPE], VisWnd, NULL,
GTCY_Active, active, TAG_END);
}
}
break;
case 'O':
case '\r':
return VIS_OKClicked();
break;
case 'C':
case VANILLA_ESC:
return VIS_CANCELClicked();
break;
}
return 0;
}
int DesignPROJECT_ABOUT( void )
{
/* routine when (sub)item "About view design..." is selected. */
EasyRequest(CurrentPro->CurrentLayout->Window, &ES_ViewDesignHelp, NULL, GetAppStr(MSG_EDVIEW_HELP_BODY));
return 0;
}
int DesignPROJECT_EXIT( void )
{
/* routine when (sub)item "Exit view design" is selected. */
return 1; /* Leave View design */
}
int DesignEDIT_UNDO( void )
{
/* routine when (sub)item "Undo" is selected. */
if (PerformUndo(CurrentPro->CurrentLayout))
Redraw(CurrentPro, CurrentPro->CurrentLayout);
else DisplayBeep(Scr);
return 0;
}
int DesignEDIT_CUT( void )
{
/* routine when (sub)item "Cut" is selected. */
if (Selected) {
SaveUndo(CurrentPro->CurrentLayout);
FillClip(RemoveVisFldInfo(CurrentPro->CurrentLayout, Selected));
OnMenu(CurrentPro->CurrentLayout->Window, FULLMENUNUM(1,4,NOSUB)); /* Edit->Paste */
Redraw(CurrentPro, CurrentPro->CurrentLayout);
}
return 0;
}
int DesignEDIT_COPY( void )
{
/* routine when (sub)item "Copy" is selected. */
if (Selected) {
FillClip(CopyVisFldInfo(Selected));
OnMenu(CurrentPro->CurrentLayout->Window, FULLMENUNUM(1,4,NOSUB)); /* Edit->Paste */
}
return 0;
}
int DesignEDIT_PASTE( void )
{
/* routine when (sub)item "Paste" is selected. */
SaveUndo(CurrentPro->CurrentLayout);
InsertVisFldInfo(CurrentPro->CurrentLayout, CopyVisFldInfo(Clip));
Redraw(CurrentPro, CurrentPro->CurrentLayout);
return 0;
}